package com.handersome.db.dao;

import java.io.Serializable;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.text.ParseException;
import java.util.Date;

import org.apache.commons.lang3.time.DateUtils;

import com.alibaba.fastjson.JSON;
import com.handersome.db.annotation.HColumn;
import com.handersome.db.annotation.HTable;
import com.handersome.db.entity.Project;
import com.handersome.db.entity.User;

/**
 * 自己实现ResultSet到对象的映射
 * @author handersome
 *
 * @version 创建时间：2017年12月18日 下午3:46:26
 */
public class BaseDaoImpl<T> {

	public static final String  URL= "jdbc:mysql://120.24.227.186/myblog";
	public static final String NAME = "com.mysql.jdbc.Driver";
	public static final String USER = "root";
	public static final String PASSWORD = "123456";
	public static Connection conn;

	public static PreparedStatement st;

	static {
		if (st == null) {
			try {
				Class.forName(NAME);
			} catch (ClassNotFoundException e) {
				e.printStackTrace();
			}
			try {
				conn = (Connection) DriverManager.getConnection(URL, USER, PASSWORD);// 和数据库的连接
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
	}

	public T get(Class<T> claz, Serializable id)
			throws NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException,
			ParseException, SQLException, IllegalAccessException, InstantiationException {
		String sql = iDQueryString(claz);
		st = conn.prepareStatement(sql);
		st.setLong(1, (Long) id);
		ResultSet rs = st.executeQuery();
		T obj = null;
		while (rs.next()) {
			obj = invoke(rs, claz);
		}
		return obj;
	}

	/**
	 * 依据类生成对应的id查询语句
	 * @param claz
	 * @return
	 */
	public String iDQueryString(Class<T> claz) {
		HTable ht = claz.getAnnotation(HTable.class);
		String tbName = ht.name();
		String tt = tbName.substring(0, 2);
		String sql = "select * from " + tbName + " as " + tt + " where " + tt + ".id = ?";
		return sql;
	}

	/**
	 * 将查询的结果映射生成对应类的实例对象
	 * @param rs
	 * @param claz
	 * @return
	 * @throws SQLException
	 * @throws NoSuchMethodException
	 * @throws SecurityException
	 * @throws IllegalArgumentException
	 * @throws InvocationTargetException
	 * @throws ParseException
	 * @throws IllegalAccessException
	 * @throws InstantiationException
	 */
	public T invoke(ResultSet rs, Class<T> claz)
			throws SQLException, NoSuchMethodException, SecurityException, IllegalArgumentException,
			InvocationTargetException, ParseException, IllegalAccessException, InstantiationException {
		T obj = claz.newInstance();
		Method[] methods = claz.getDeclaredMethods();
		for (int i = 0; i < methods.length; i++) {
			Method m = methods[i];
			String name = m.getName();
			if (isGetMethod(name)) {
				HColumn ann = m.getAnnotation(HColumn.class);
				String cln = ann.name();
				String value = rs.getString(cln);
				String setName = "set" + name.substring(3);
				Method setm = claz.getDeclaredMethod(setName, m.getReturnType());
				// System.out.println("方法 " + setm + " 值" + value);
				if (m.getReturnType().equals(Integer.class)) {
					setm.invoke(obj, Integer.parseInt(value));
				} else if (m.getReturnType().equals(Long.class)) {
					setm.invoke(obj, Long.parseLong(value));
				} else if (m.getReturnType().equals(String.class)) {
					setm.invoke(obj, value);
				} else if (m.getReturnType().equals(Date.class)) {
					setm.invoke(obj, DateUtils.parseDate(value, "yy-MM-dd hh:mm:ss.S"));
				} else {
					setm.invoke(obj, Integer.parseInt(value));
				}
			}
		}
		System.out.println(Thread.currentThread().getName() + " : " + JSON.toJSON(obj).toString());
		return obj;

	}

	public static boolean isGetMethod(String name) {
		return name.startsWith("get");
	}

	public static boolean isSetMethod(String name) {
		return name.startsWith("set");
	}

	public static void main(String[] args) throws NoSuchMethodException, SecurityException, IllegalArgumentException,
			InvocationTargetException, ParseException, SQLException, IllegalAccessException, InstantiationException {
		BaseDaoImpl<User> u = new BaseDaoImpl<User>();
		BaseDaoImpl<Project> u1 = new BaseDaoImpl<Project>();
		u.get(User.class, 1L);
		u1.get(Project.class, 1L);
	}

}
